package com.lzq.course.file.controller.admin;

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.AppendObjectRequest;
import com.aliyun.oss.model.AppendObjectResult;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectRequest;
import com.lzq.course.server.dto.FileDto;
import com.lzq.course.server.dto.ResponseDto;
import com.lzq.course.server.enums.FileUseEnum;
import com.lzq.course.server.service.FileService;
import com.lzq.course.server.util.Base64ToMultipartFile;
import com.lzq.course.server.util.UuidUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;

/**
 * 在 oss 上传文件
 * 前端传来了分片 这里使用oss的追加上传
 */
@RestController
@RequestMapping("/admin")
public class OssController {

    private final static Logger LOG = LoggerFactory.getLogger(OssController.class);

    public static final String BUSINESS_NAME = "oss文件上传";

    @Value("${oss.accessKeyId}")
    private String accessKeyId;

    @Value("${oss.accessKeySecret}")
    private String accessKeySecret;

    @Value("${oss.endpoint}")
    private String endpoint;

    @Value("${oss.bucketName}")
    private String bucketName;

    @Value("${oss.domain}")
    private String ossDomain;

    @Resource
    private FileService fileService;

    /**
     * 上传文件
     * @return
     */
    @RequestMapping("/oss-append")
    public ResponseDto ossUpload(@RequestBody FileDto fileDto) throws IOException {
        ResponseDto responseDto = new ResponseDto();

        LOG.info("文件上传开始");
        Integer shardIndex = fileDto.getShardIndex();
        Integer shardSize = fileDto.getShardSize();
        String use = fileDto.getUse();
        String suffix = fileDto.getSuffix();
        String key64 = fileDto.getKey();
        MultipartFile shard = Base64ToMultipartFile.base64ToMultipart(fileDto.getShard());

        FileUseEnum useEnum = FileUseEnum.getByCode(use); // 用途
        String dir = useEnum.name().toLowerCase(); // course or teacher

        // 注意：这里不能使用File.separator 因为这个是文件分隔符，不是字符串分隔符
        String path = new StringBuilder(dir)
                .append("/")
                .append(key64)
                .append(".")
                .append(suffix)
                .toString(); // course\teacher\xxxx.jpg

        // 1.创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        ObjectMetadata meta = new ObjectMetadata();
        // 指定上传的内容类型。
        meta.setContentType("text/plain");

        // 通过AppendObjectRequest设置多个参数。
        AppendObjectRequest appendObjectRequest = new AppendObjectRequest(bucketName, path,
                new ByteArrayInputStream(shard.getBytes()), meta);

        // 设置文件的追加位置。
        appendObjectRequest.setPosition((long) ((shardIndex - 1) * shardSize));
        AppendObjectResult appendObjectResult = ossClient.appendObject(appendObjectRequest);
        // 文件的64位CRC值。此值根据ECMA-182标准计算得出。
        System.out.println(appendObjectResult.getObjectCRC());

        // 关闭OSSClient。
        ossClient.shutdown();

        LOG.info("保存文件记录开始");
        fileDto.setPath(path); // 相对路径
        fileService.save(fileDto);

        fileDto.setPath(ossDomain + path); // 文件路径给前端
        responseDto.setContent(fileDto);
        return responseDto;
    }

    /**
     * 单文件上传 简单上传
     * 【测试代码】
     * @param file
     * @param use
     * @return
     * @throws Exception
     */
    @PostMapping("/oss-simple")
    public ResponseDto fileUpload(@RequestParam MultipartFile file, String use) throws Exception {
        LOG.info("上传文件开始");
        FileUseEnum useEnum = FileUseEnum.getByCode(use);
        String key = UuidUtil.getShortUuid();
        String fileName = file.getOriginalFilename();
        String suffix = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase();
        String dir = useEnum.name().toLowerCase();
        String path = dir + "/" + key + "." + suffix;

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);

        PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, path, new ByteArrayInputStream(file.getBytes()));

        // 上传字符串。
        ossClient.putObject(putObjectRequest);

        ResponseDto responseDto = new ResponseDto();
        FileDto fileDto = new FileDto();
        fileDto.setPath(ossDomain + path);
        responseDto.setContent(fileDto);

        return responseDto;
    }
}
